//
//  XTRequestCenter.swift
//  Kool Car
//
//  Created by huangweiqiang on 2021/12/16.
//

import UIKit
import RxSwift
import RxCocoa
import Moya
import Alamofire
import MJRefresh
import ObjectMapper
import SwiftOverlayShims
import Reachability
// 1.定义一个闭包类型
//格式: typealias 闭包名称 = (参数名称: 参数类型) -> 返回值类型
typealias requestCompletionBlock = (_ data: Any) -> Void



// MARK: - Provider setup
// 序列化
private func JSONResponseDataFormatter(_ data: Data) -> Data {
    do {
        let dataAsJSON = try JSONSerialization.jsonObject(with: data)
        let prettyData =  try JSONSerialization.data(withJSONObject: dataAsJSON, options: .prettyPrinted)
        return prettyData
    } catch {
        return data // fallback to original data if it can't be serialized.
    }
}


public func defaultAlamofireManager() -> Manager {
    
    let configuration = URLSessionConfiguration.default
    configuration.requestCachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData
    configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders
    let policies: [String: ServerTrustPolicy] = [
        "https://www.baidu.com": .disableEvaluation
    ]
    let manager = Alamofire.SessionManager(configuration: configuration,serverTrustPolicyManager: ServerTrustPolicyManager(policies: policies))
    
    manager.startRequestsImmediately = false
    
    return manager
}


class XTRequestCenter: NSObject {
    static let shared = XTRequestCenter()
    let reachability = try! Reachability()
    //2. 声明一个变量
    var callBack: requestCompletionBlock?
    var bag : DisposeBag = DisposeBag()
    
    let provider = MoyaProvider<APIManager>.init(plugins: [NetworkLoggerPlugin.init(verbose: false, responseDataFormatter: JSONResponseDataFormatter)])
    let requestConmond = PublishSubject<Bool>()
    
    /// 获数据数
    ///
    /// - Parameter target: 返回json
    func sendRequestJson(target: APIManager ,
                         finished: @escaping requestCompletionBlock,
                         error:@escaping (_ err: NSError?) -> Void) {
        if reachability.connection == .unavailable {
            let connectError = NSError.init(domain: MMLocalizedString("msg_netwok_cant_use", comment: "当前网络不可用，请检查您的网络"), code: 201, userInfo: nil)
            error(connectError)
            return
        }
        
        self.provider.rx.request(target)
            .mapJSON()
            .subscribe(onSuccess: { (response) in
                finished(response)
            }, onError: { (tterror) in
                print(tterror)
                do {
                    let err = tterror as NSError
                    error(err)
                    if err.code == 401 {
                        //token过期的话跳转登录页 置false
                        UserModule.shared.token = nil
                        UserModule.shared.isLogined = false
                        XTManageCenter.shared.jumpToLoginView()
                    }
                }
            })
            .disposed(by: self.bag)
    }
 
    /// 返回的数据以对像objcet形式返回
    ///
    /// - Parameters:
    ///   - target:
    ///   - type:
    ///   - finished:
    ///   - error:
    func sendRequestMappableTargetObject<T: Mappable>(target: APIManager,
                                                      objectType type: T.Type,
                                                      finished: requestCompletionBlock? = nil,
                                                      error: ((_ err: NSError?) -> Void)? = nil) {
        
        
        if reachability.connection == .unavailable {
            reachability.stopNotifier()
            let connectError = NSError.init(domain: MMLocalizedString("msg_netwok_cant_use", comment: "当前网络不可用，请检查您的网络"), code: 201, userInfo: nil)
            error?(connectError)
            return
        }
        
        self.provider.rx.request(target)
            .mapJSON().asObservable().mapObject(type: type)
            .subscribe(onNext: { (model) in
                let tempCode = ((model.toJSON())["code"] ?? 0) as? String
                let msg = (model.toJSON())["msg"] as? String
                switch tempCode {
                case "50008", "401":
//                    let err = NSError.init(domain: MMLocalizedString("not_login", comment: "未登录"), code: 401, userInfo: nil)
//                    error?(err)
                    //token过期的话跳转登录页 置false
                    self.jumpLoginView()
                case "404":
                    let err = NSError.init(domain: "404", code: 404, userInfo: nil)
                    error?(err)
                case "500":
                    let tempErr = NSError.init(domain: msg ?? MMLocalizedString("connect_error", comment: "服务器异常"), code: 6, userInfo: ["6": msg ?? MMLocalizedString("connect_error", comment: "服务器异常")])
                    error?(tempErr)
                default:
                    finished?(model)
                }

            }, onError: { (tterror) in
                do {
                    let err = tterror as NSError
                    
                    switch err.code {
                    case 1:
                        ///解析出错 Failed to map data to JSON
                        let tempErr = NSError.init(domain: MMLocalizedString("jsonError", comment: "解析异常"), code: 1,
                                                   userInfo: ["1": MMLocalizedString("jsonError", comment: "解析异常")])
                        error?(tempErr)
                    case 6:
                        //服务器500
                        let tempErr = NSError.init(domain: err.domain, code: 6, userInfo: ["6": err.domain])
                        error?(tempErr)
                    case 401:
                        error?(err)
                        //token过期的话跳转登录页 置false
                        self.jumpLoginView()
                    default:
                        error?(err)
                    }
                }
            }, onCompleted: nil, onDisposed: nil)
            .disposed(by: self.bag)
    }
    
    /**
     跳转登录页
     */
    func jumpLoginView(){
        let tbVC = UIApplication.shared.keyWindow?.rootViewController
        if tbVC!.isKind(of: BaseTabbarController.self) {
            let tabbarVC = tbVC as! BaseTabbarController
//            _ = tabbarVC.childViewControllers.map { navi in
//                (navi as? BaseNavigationController)?.popToRootViewController(animated: false)
//            }
            tabbarVC.selectedIndex = 0
            UserModule.shared.token = nil
            UserModule.shared.isLogined = false
            XTManageCenter.shared.jumpToLoginView()
        }
    }
    
    
    func sendGetRequestByUserCenter(byUrl: String, finished: @escaping requestCompletionBlock,
                                    error: @escaping (_ err: NSError?) -> Void)  {
        let headers = ["Content-Type": "application/json;charset=UTF-8"]
        let url1 = byUrl.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
        Alamofire.request(url1, method: .get
            , parameters: nil, encoding: URLEncoding.default, headers: headers).responseJSON { response in
                if (response.data != nil) {
                    let jsonString = String(data: response.data! , encoding: String.Encoding.utf8)
                    finished(jsonString!)
                }else{
                    let tempErr = NSError.init(domain: MMLocalizedString("connect_error", comment: "服务器异常"),
                                               code: 6,
                                               userInfo: ["6": MMLocalizedString("connect_error", comment: "服务器异常")])
                    error(tempErr)
                }
        }
    }
    
    func sendPOSTRequestByUserCenter(byUrl: String, paramData: [String: Any], finished: @escaping requestCompletionBlock,error: @escaping (_ err: NSError?) -> Void)  {
//        let headers = ["Content-Type": "application/json;charset=UTF-8"]
//        let url1 =  byUrl.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
//        Alamofire.request(url1, method: .post, parameters: paramData, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in
            //JSON--->data--->JSON字符串
            //success(response.data as AnyObject)
//            if (response.data != nil) {
//                let jsonString = String(data: response.data! , encoding: String.Encoding.utf8)
//                finished(jsonString!)
//            }else{
//                let tempErr = NSError.init(domain: MNSLocalizedString("network_exception_check_network", comment: "网络异常，请检查网络"), code: 6, userInfo: ["6":MNSLocalizedString("network_exception_check_network", comment: "网络异常，请检查网络")])
//                error(tempErr)
//            }
//        }
    }
    
    
    //上传图片到OSS服务器
    public static func ossUploadImage(imageData : Data, uploadURL:String, imageName:String, success : @escaping (_ response : AnyObject)->(), failture : @escaping (_ error : NSError)->()){
        let reachability = try! Reachability()
        if reachability.connection == .unavailable {
            (UIApplication.shared.keyWindow?.rootViewController?.view)?.makeToast(message: MMLocalizedString("network_exception_check_network", comment: "网络异常"), duration: 1.4)
            return
        }
        var urlRequest:URLRequest = URLRequest(url: URL(string: uploadURL)!)
        /*缓存属性设置*/
        urlRequest.cachePolicy = .returnCacheDataElseLoad
        /*请求头与请求体属性设置*/
        urlRequest.httpBody = imageData
        urlRequest.httpMethod = "PUT" //post 方法
        
        urlRequest.addValue("application/octet-stream", forHTTPHeaderField: "Content-Type")
        urlRequest.addValue(UserModule.shared.token ?? "", forHTTPHeaderField: "Authorization")
        
        let sessionConfigure = URLSessionConfiguration.default
        sessionConfigure.timeoutIntervalForRequest = 60
        sessionConfigure.requestCachePolicy = .reloadIgnoringLocalCacheData
        let session = URLSession(configuration: sessionConfigure)
        let task =  session.dataTask(with: urlRequest) { (data, response, error) in
            guard data != nil else {
                return
            }
            DispatchQueue.main.async {
                //进到这里说明成功了
                if error == nil {
                    //说明成功
                    let result = ["code":"1","msg": MMLocalizedString("upload_success", comment: "上传成功")];
                    success(result as AnyObject)
                }else{
                    //说明失败
                    let ee = NSError.init(domain: MMLocalizedString("upload_failed", comment: "上传失败"), code: 400, userInfo: nil)
                    failture(ee)
                }
            }
        }
        task.resume() //开始执行
    }
    
    
    //上传图片到服务器
    public static func uploadImage(imageData : Data, uploadURL:String, imageName:String, success : @escaping (_ response : AnyObject)->(), failture : @escaping (_ error : NSError)->()){
        let reachability = try! Reachability()
        if reachability.connection == .unavailable {
            (UIApplication.shared.keyWindow?.rootViewController?.view)?.makeToast(message: MMLocalizedString("network_exception_check_network", comment: "网络异常"), duration: 1.4)

            return
        }
        let headers = ["Content-Type":"multipart/form-data; boundary=----WebKitFormBoundaryIeCcznumOkLAYyOh;",
                       "fileType":"IMAGE","Accept":"image/webp,image/apng,image/*,*/*;q=0.8",
                       "Authorization":UserModule.shared.token ?? ""]
        Alamofire.upload(
            multipartFormData: { multipartFormData in
                //采用post表单上传
                // 参数解释：
                //withName:和后台服务器的name要一致 ；fileName:可以充分利用写成用户的id，但是格式要写对； mimeType：规定的，要上传其他格式可以自行百度查一下
                multipartFormData.append(imageData, withName: "file", fileName: imageName, mimeType: "image/jpeg")
                
        },to: uploadURL,
          headers:headers,
          encodingCompletion: { encodingResult in
            switch encodingResult {
            case .success(let upload, _, _):
                //连接服务器成功后，对json的处理
                upload.responseJSON { response in
                    //解包
                    guard let result = response.result.value else { return }
                    success(result as AnyObject)
                }
                //获取上传进度
                upload.uploadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in
                    //                    print("图片上传进度: \(progress.fractionCompleted)")
                }
            case .failure(let encodingError):
                //打印连接失败原因
                printLog(encodingError)
                failture(encodingError as NSError)
            }
        })
    }
    
    
    //下载pdf
    public static func downLoadPdf(url:String, success : @escaping (_ response : AnyObject)->(), failture : @escaping (_ error : NSError)->()){
        let reachability = try! Reachability()
        if reachability.connection == .unavailable {
            (UIApplication.shared.keyWindow?.rootViewController?.view)?.makeToast(message: MMLocalizedString("network_exception_check_network", comment: "网络异常"), duration: 1.4)
            return
        }
        
        let headers = ["Content-Type":"application/pdf;",
                       "Authorization":UserModule.shared.token ?? ""]
        if (url == "") {
            return
        }
        Alamofire.request(url, headers: headers).responseJSON { response in
            printLog(response.data)
            success(response.data as AnyObject)
        }
    }
    
    //
    public static func fetchByUrl(url:String, success : @escaping (_ response : AnyObject)->(), failture : @escaping (_ error : NSError)->()){
        let reachability = try! Reachability()
        if reachability.connection == .unavailable {
            (UIApplication.shared.keyWindow?.rootViewController?.view)?.makeToast(message: MMLocalizedString("network_exception_check_network", comment: "网络异常"), duration: 1.4)
            return
        }
        
        let headers = ["Content-Type": "application/json;charset=UTF-8"]
        let url1 =  url.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
        Alamofire.request(url1, method: .get
            , parameters: nil, encoding: URLEncoding.default, headers: headers).responseJSON { response in
                success(response.data as AnyObject)
        }
        
    }
    
}
